package com.alibaba.algo.utils;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
public class CacheUtil {

    private static final String REDIS_KEY_USER_ID_MAP = "USER_ID_MAP";
    public static final String REDIS_KEY_USER_ID_MAP_EMP = "EMP";
    public static final String REDIS_KEY_USER_ID_MAP_ACT = "ACT";

    private static final String REDIS_KEY_USER_INFO_PREFIX = "USER_INFO:UID";
    public static final String REDIS_KEY_USER_INFO_USER = "USER";
    public static final String REDIS_KEY_USER_INFO_EMPLOYEE = "EMPLOYEE";
    public static final String REDIS_KEY_USER_INFO_ROLE = "ROLE";
    public static final String REDIS_KEY_USER_INFO_ORG = "ORG";
    public static final String REDIS_KEY_USER_INFO_POSITION = "POSITION";
    public static final String REDIS_KEY_USER_INFO_GROUP = "GROUP";

    public static final int DELAY_MILLIS = 5000;

    /**
     * 分散失效时间 24小时-26小时之间
     * 24小时=24*60*60=86400秒
     * 26小时=26*60*60=93600秒
     *
     * @return
     */
    public static int randomExpireSeconds() {
        Integer min = 86400;
        Integer max = 93600;
        SecureRandom secureRandom = null;
        int result = min;
        try {
            secureRandom = SecureRandom.getInstance("SHA1PRNG");
            result = secureRandom.nextInt(max) % (max - min + 1) + min;
        } catch (NoSuchAlgorithmException e) {
            log.error("CacheUtil.randomExpireSeconds Exception", e);
        }
        return result;
    }

    public static String getUserIdMapEmpKey(String employeeCode) {
        return String.format("%s:%s%s", REDIS_KEY_USER_ID_MAP, REDIS_KEY_USER_ID_MAP_EMP, employeeCode);
    }

    public static String getUserIdMapActKey(String account) {
        return String.format("%s:%s%s", REDIS_KEY_USER_ID_MAP, REDIS_KEY_USER_ID_MAP_ACT, account);
    }

    public static String getUserInfoKey(Long userId, String type) {
        return String.format("%s%s:%s", REDIS_KEY_USER_INFO_PREFIX, userId + "", type);
    }

    public static String getUserInfoUserKey(Long userId) {
        return getUserInfoKey(userId, REDIS_KEY_USER_INFO_USER);
    }

    public static String getUserInfoEmployeeKey(Long userId) {
        return getUserInfoKey(userId, REDIS_KEY_USER_INFO_EMPLOYEE);
    }

    public static String getUserInfoRoleKey(Long userId) {
        return getUserInfoKey(userId, REDIS_KEY_USER_INFO_ROLE);
    }

    public static String getUserInfoOrgKey(Long userId) {
        return getUserInfoKey(userId, REDIS_KEY_USER_INFO_ORG);
    }

    public static String getUserInfoPositionKey(Long userId) {
        return getUserInfoKey(userId, REDIS_KEY_USER_INFO_POSITION);
    }

    public static String getUserInfoGroupKey(Long userId) {
        return getUserInfoKey(userId, REDIS_KEY_USER_INFO_GROUP);
    }

    public static Set<String> buildDataTypeSet(String... args) {
        Set<String> dataTypeSet = new HashSet<>();
        if (null == args || args.length <= 0) {
            log.info("buildDataTypeSet args is empty");
            return dataTypeSet;
        }
        for (String arg : args) {
            if (StringUtils.isEmpty(arg)) {
                continue;
            }
            dataTypeSet.add(arg);
        }
        return dataTypeSet;
    }

    public static void setObjectValueInThread(final String key, Object obj) {
        ThreadPoolUtil.getThreadPool().submit(() -> {
            String result = JedisUtil.setObjectValue(key, obj, randomExpireSeconds());
            log.info("setObjectValueInThread key:{},obj:{},result:{}", key, JSON.toJSONString(obj), result);
        });
    }

    public static void setStringValueInThread(String key, String value) {
        ThreadPoolUtil.getThreadPool().submit(() -> {
            String result = JedisUtil.setStringValue(key, value, randomExpireSeconds());
            log.info("setStringValueInThread key:{},obj:{},result:{}", key, JSON.toJSONString(value), result);
        });
    }

    /**
     * 过滤出删除失败的清单，key不存在或者结构等于0标识删除失败，小于0（-1）表示不存在，大于0表示删除成功
     *
     * @param resultMap
     * @param oriKeys
     * @return
     */
    public static List<String> getDelFailKeys(Map<String, Long> resultMap, List<String> oriKeys) {
        //resultMap为空，表示都没有结果，原keys都需要再次删除
        if (MapUtil.isEmpty(resultMap)) {
            return oriKeys;
        }
        List<String> delFailKeys = new ArrayList<>();
        for (String key : oriKeys) {
            if (resultMap.containsKey(key)) {
                Long rtnValue = resultMap.get(key);
                if (0 == rtnValue) {
                    delFailKeys.add(key);
                }
            } else {
                delFailKeys.add(key);
            }
        }
        return delFailKeys;
    }
}
